package com.coms514.scheduleme;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.StringTokenizer;

import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.api.client.util.DateTime;
import com.google.api.services.calendar.Calendar;
import com.google.api.services.calendar.model.Event;
import com.google.api.services.calendar.model.EventDateTime;
import com.google.api.services.calendar.model.EventReminder;
import com.google.api.services.calendar.model.Events;


import android.os.Bundle;
import android.accounts.AccountManager;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.util.Log;
import android.view.ContextMenu;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ContextMenu.ContextMenuInfo;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

/**
 * Asynchronous Events that also takes care of common needs, such as displaying progress,
 * authorization, exception handling, and notifying UI when operation succeeded.
 * 
 * @author Qilin Li
 * 
 * */

public class ShowEventsActivity extends Activity {
	
	  private final static int EDIT_EVENT_REQUEST = 0;
	  private final static int ADD_EVENT_REQUEST = 1;  // request to create a new event
	  private final static int SHOW_EVENT_REQUEST = 2;
	  private final static int EDIT_ADD_EVENT_REQUEST = 3; // for QR scanning, start edit activity first, then create new event, not update a event
	  public static final int SCAN_EVENT_REQUEST = 0x0000c0de; // Only use bottom 16 bits
	  
	  private static final int CONTEXT_EDIT = 0;
	  private static final int CONTEXT_DELETE = 1;
	  
	  com.google.api.services.calendar.Calendar client;
	  public String currentCalendarId;
	  EventModel model = new EventModel(client, currentCalendarId);
	  int numAsyncTasks;
	  private ListView listView;
	  ArrayAdapter<EventInfo> adapter;
	  private ScheduleMe myState;
	  
	    
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		//numAsyncTasks = 0;
		setContentView(R.layout.activity_show_events);
		listView = (ListView) findViewById(R.id.events_list);
	    // register a pop-up menu when when you long-click certain list item
	    registerForContextMenu(listView);
	    // set setOnItemClickListener
	    listView.setOnItemClickListener(myOnItemClickListener);

	    
		/*
		ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,
				new String[] {"Item0","Item1","Item2","Item3","Item4","Item5","Item6","Item7","Item8","Item9"});
		listView.setAdapter(adapter);
		*/
		myState = ((ScheduleMe)getApplicationContext());
		client = myState.getClient();
		currentCalendarId = myState.getSelectedCalendarId();

		model = new EventModel(client, currentCalendarId);

		AsyncLoadEvents.run(this);
	}
	
	  OnItemClickListener myOnItemClickListener = new OnItemClickListener() {
  	  	  @Override
		  // arg1: view, arg2: position, arg3: id
	  	  public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
					long arg3) {
				// TODO Auto-generated method stub
				 Toast.makeText(getApplicationContext(), "You pressed "+((TextView) arg1).getText(), 
						 Toast.LENGTH_SHORT).show();
				 //myState.setSelectedCalendarId(model.get((String)((TextView) arg1).getText()).id);
				 Intent intent = new Intent(ShowEventsActivity.this, EventContentActivity.class);
				 
				  int eventIndex = arg2;
				  if (eventIndex < adapter.getCount()) {
					  myState.eventInfo = adapter.getItem(eventIndex);
				  }
				    	
				   startActivityForResult(intent, SHOW_EVENT_REQUEST);	
				  	
				}
	    };
	
	void refreshView() {
			  // Refresh the events list
	    	 adapter = new ArrayAdapter<EventInfo>(
	        	//  android.R.layout.simple_list_item_1 is a built-in XML layout 
	         this, android.R.layout.simple_list_item_1, model.toSortedArray()) {

	            @Override
	          public View getView(int position, View convertView, ViewGroup parent) {
	            // by default it uses toString; override to use summary instead
	            TextView view = (TextView) super.getView(position, convertView, parent);
	            EventInfo eventInfo = getItem(position);
	            view.setText(eventInfo.summary);
	            return view;
	          }
	        };
	        listView.setAdapter(adapter);
	}
	
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.show_events, menu);
		return true;
	}
	
	  @Override
	  public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
	    super.onCreateContextMenu(menu, v, menuInfo);
	    menu.add(0, CONTEXT_EDIT, 0, R.string.edit_event);
	    menu.add(0, CONTEXT_DELETE, 0, R.string.delete_event);
	  }
	
	  @Override
	  public boolean onContextItemSelected(MenuItem item) {
	    // extra information set by the View that added this menu item to the menu
	    AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
	    int eventIndex = (int) info.id;
	    if (eventIndex < adapter.getCount()) {
	      final EventInfo eventInfo = adapter.getItem(eventIndex);
	      // FIXME: write eventInfo into Application Context
	      switch (item.getItemId()) {
	        case CONTEXT_EDIT:
	          myState.eventInfo = eventInfo;
	          startAddOrEditEventActivity("edit");
	          return true;
	        case CONTEXT_DELETE:
	          new AlertDialog.Builder(this).setTitle(R.string.delete_event_title)
	              .setMessage(eventInfo.summary)
	              .setCancelable(false)
	              .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {

	                public void onClick(DialogInterface dialog, int which) {
	                    new AsyncDeleteEvent(ShowEventsActivity.this, currentCalendarId, eventInfo).execute();
	                }
	              })
	              .setNegativeButton(R.string.no, null)
	              .create()
	              .show();

	          return true;
	      }
	    }
	    return super.onContextItemSelected(item);
	  }
	


	@Override
	  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
	    super.onActivityResult(requestCode, resultCode, data);
	    switch (requestCode) { 

	      case ADD_EVENT_REQUEST:
	    	  if (resultCode == Activity.RESULT_OK) {    		  
	    		  /* Create a new event */    		  
	    	        EventInfo eventInfo = myState.eventInfo;
					new AsyncInsertEvent(this, currentCalendarId, eventInfo).execute();
	    	  }
	    	  break;
	      case EDIT_EVENT_REQUEST:
	    	  if (resultCode == Activity.RESULT_OK) {    		  
	    		  /* Edit event */    
	    	        EventInfo eventInfo = myState.eventInfo;
					new AsyncUpdateEvent(this, currentCalendarId, eventInfo).execute();
	    	  }
	    	  break;
	      case SHOW_EVENT_REQUEST:
	    	  if (data.getStringExtra("edit_or_show").compareTo("edit") == 0)
	    		  startAddOrEditEventActivity("edit");
	    	  break;
	      case SCAN_EVENT_REQUEST:
	    	  IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
			  Log.v("myTest", scanResult.getContents());
			  /* parse result to event format */
			  Log.v("myTest", "beging parse");
			  EventInfo eventInfo = parseQRcodeToEvent(scanResult);
			  Log.v("myTest", "end parse");
			  
			  /* Create a new event */    		  
  	          myState.eventInfo = eventInfo;
  	          startAddOrEditEventActivity("edit_add");
	    	  break;
	      case EDIT_ADD_EVENT_REQUEST:
	    	  if (resultCode == Activity.RESULT_OK) {    		  
	    		  /* Create a new event */    		  
					new AsyncInsertEvent(this, currentCalendarId, myState.eventInfo).execute();
	    	  }
	    	  break;
	    }
	  }
	
	/* Self-Defined Format
	* TYPE:Event
	* SUMMARY:Title
	* LOCATION:Coover Hall
	* DESCRIPTION:What
	* DSTART:2013-11-15
	* TSTART:10:00:00  //NULL means all day event
	* DEND:2013-11-15 
	* TEND:11:00:00   //NULL means all day event
	* REPEAT:RRULE:FREQ=WEEKLY;UNTIL=20131207T102500Z  // NULL means no repeating
	 */
	public EventInfo parseQRcodeToEvent(IntentResult scanResult) {
		EventInfo eventInfo = new EventInfo();
		String rawData = scanResult.getContents();
		StringTokenizer item = new StringTokenizer(rawData, ":" );
		String str = item.nextToken(":"); //"TYPE"
		if (str.compareTo("TYPE") != 0) {
			Log.v("myTest", "TYPE = " + str);
			return null;
		} else {
			str = item.nextToken("\n").substring(1); 
			if (str.compareTo("Event") != 0) {
				Log.v("myTest", "Err: unrecognized type, " + str);
				return null;
			}
		}
		
		while (item.hasMoreTokens()) {
			str = item.nextToken(":").substring(1); 
			Log.v("myTest", str);
			if (str.compareTo("SUMMARY") == 0) {
				/* event title */
				str = item.nextToken("\n").substring(1); // remove ":", get "Event title"
				Log.v("myTest", "SUMMARY: " + str);
				eventInfo.summary = str;
				
			} else if (str.compareTo("LOCATION") == 0) {
				/* Location */
				str = item.nextToken("\n").substring(1); 
				Log.v("myTest", "LOCATION: " + str);
				eventInfo.location = str;
				
			} else if (str.compareTo("DESCRIPTION") == 0) {
				/* Descripton */
				str = item.nextToken("\n").substring(1); 
				Log.v("myTest", "DESCRIPTION: " + str);
				eventInfo.description = str;
				
			} else if (str.compareTo("DSTART") == 0) {
				/* Date Start */
				str = item.nextToken("\n").substring(1); 
				Log.v("myTest", "DSTART: " + str);
				eventInfo.startDate.setDate(str);
				
			} else if (str.compareTo("TSTART") == 0) {
				/* Time Start */
				str = item.nextToken("\n").substring(1); 
				Log.v("myTest", "TSTART: " + str);
				if (str.compareTo("NULL") == 0) {
					eventInfo.allDayEvent = true;
				} else {
					eventInfo.allDayEvent = false;
					eventInfo.startTime.setTime(str);
				}
				
			} else if (str.compareTo("DEND") == 0) {
				/* Date End */
				str = item.nextToken("\n").substring(1);
				Log.v("myTest", "DEND: " + str);
				eventInfo.endDate.setDate(str);
				
			} else if (str.compareTo("TEND") == 0) {
				/* Time End */
				str = item.nextToken("\n").substring(1);
				Log.v("myTest", "TEND: " + str);
				if (str.compareTo("NULL") == 0) {
					eventInfo.allDayEvent = true;
				} else {
					eventInfo.allDayEvent = false;
					eventInfo.endTime.setTime(str);
				}
				
			} else if (str.compareTo("REPEAT") == 0) {	
				/* Repeating Rule */
				str = item.nextToken("\n").substring(1); 
				Log.v("myTest", "REPEAT: " + str);
				if (str.compareTo("NULL") == 0) {
					eventInfo.repeating = false;
				} else {
					eventInfo.repeating = true;
					eventInfo.repeatRule.getRepeatRule(Arrays.asList(str));
				}
				
			}

		}
		
		return eventInfo;
	}
	
	public void onAddClick(View view) {
		startAddOrEditEventActivity("add");
	}
	
	public void onScanClick(View view) {
		IntentIntegrator integrator = new IntentIntegrator(ShowEventsActivity.this, SCAN_EVENT_REQUEST);
    	integrator.initiateScan();
	}
	
	private void startAddOrEditEventActivity(String add_or_edit) {
		// TODO Auto-generated method stub
	    Intent intent = new Intent(this, AddOrEditEventActivity.class);
	    
	    //intent.putExtra("summary", calendarInfo.summary);
	    if (add_or_edit.compareTo("add") == 0) {
		    intent.putExtra("add_or_edit", "add");
	    	startActivityForResult(intent, ADD_EVENT_REQUEST);
	    } else if (add_or_edit.compareTo("edit") == 0) {
	    	intent.putExtra("add_or_edit", "edit"); 
	    	startActivityForResult(intent, EDIT_EVENT_REQUEST);	
	    } else if (add_or_edit.compareTo("edit_add") == 0) {
	    	intent.putExtra("add_or_edit", "edit");
	    	startActivityForResult(intent, EDIT_ADD_EVENT_REQUEST);	
	    } else {
	    	Log.v("myTest", "Err: " + "No activity mode found");
	    }
	}
	 
}


